﻿using System.Diagnostics;
using System.Threading.Tasks;

namespace Red.Scripts.Defines.Scc
{
    public class Connector
    {
        #region Private Data

        private Launcher _launcher;
        private Connection _connection;

        private Task<bool> _task;

        #endregion Private Data

        #region C-Tor

        public Connector( Launcher launcher, Connection connection )
        {
            _launcher = launcher;
            _connection = connection;
        }

        #endregion C-Tor

        #region Public Methods

        public async Task<bool> Connect()
        {
            if ( _task == null )
                _task = Task.Run( async () => { return await ConnectInternal(); } );

            await _task;

            return _task.Result;
        }

        public void Disconnect()
        {
            _connection.Disconnect();
            _launcher.Shutdown();
            _task = null;
        }

        #endregion Public Methods

        #region Private Methods

        private async Task<bool> ConnectInternal()
        {
            bool connected = false;

            do
            {
                connected = await RunAndConnect();

                if ( !connected && _launcher.CouldNotFindExe )
                    break;

            } while ( !connected );

            return _connection.IsConnected;
        }

        private async Task<bool> RunAndConnect()
        {
            string pathToExe = null;

            const int maxLaunchAttempts = 5;
            for ( int launchAttempts = 0; launchAttempts < maxLaunchAttempts; ++launchAttempts )
            {
                Debug.Print( $"Scc Launch attempt {launchAttempts}/{maxLaunchAttempts}" );
                _launcher.Launch();

                if ( _launcher.IsRunning )
                {
                    switch ( await _connection.Connect() )
                    {
                        case Connection.Result.VersionFailure:
                            Debug.Print( $"{_launcher.PathToExe} is out of date, ignoring..." );
                            _launcher.Shutdown();
                            return false;

                        case Connection.Result.ChannelFailure:
                            Debug.Print( $"{_launcher.PathToExe} did not respond, retrying..." );
                            pathToExe = _launcher.PathToExe;
                            _launcher.Shutdown();
                            await Task.Delay( 500 );
                            break;

                        case Connection.Result.Success:
                            return true;
                    }
                }
                else if ( _launcher.CouldNotFindExe )
                {
                    Debug.Print( $"Exhausted list of possible SCC executables" );
                    break;
                }
                else
                {
                    await Task.Delay( 500 );
                }
            }

            return false;
        }

        #endregion Private Methods
    }
}
